<html>
<head>
    <meta charset="utf-8"/>
<meta name="description" content=""/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>为小白设计的电池教程（DSDT） | 神楽小白(GZ小白)</title>
<link rel="shortcut icon" href="https://gzxiaobai.github.io/favicon.ico?v=1589593333430">
<link href="https://cdn.bootcss.com/font-awesome/5.11.2/css/all.css" rel="stylesheet">
<link rel="stylesheet" href="https://gzxiaobai.github.io/styles/main.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
      integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">

<script src="https://cdn.bootcss.com/highlight.js/9.15.10/highlight.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.10/languages/dockerfile.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.10/languages/dart.min.js"></script>
<script src="https://cdn.bootcss.com/highlight.js/9.15.10/languages/go.min.js"></script>
<script src="https://cdn.bootcss.com/moment.js/2.23.0/moment.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js"
        integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n"
        crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"
        integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo"
        crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
        integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
        crossorigin="anonymous"></script>

<!-- DEMO JS -->
<!--<script src="media/scripts/index.js"></script>-->



    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.10.0/katex.min.css">
</head>
<body>
<div class="main gt-bg-theme-color-first">
    <nav class="navbar navbar-expand-lg">
    <div class="navbar-brand">
        <img class="user-avatar" src="/images/avatar.png" alt="头像">
        <div class="site-name gt-c-content-color-first">
            神楽小白(GZ小白)
        </div>
    </div>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
            aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <i class="fas fa-bars gt-c-content-color-first" style="font-size: 18px"></i>
    </button>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <div class="navbar-nav mr-auto" style="text-align: center">
            
                <div class="nav-item">
                    
                        <a href="/" class="menu gt-a-link">
                            首页
                        </a>
                    
                </div>
            
                <div class="nav-item">
                    
                        <a href="/archives" class="menu gt-a-link">
                            归档
                        </a>
                    
                </div>
            
                <div class="nav-item">
                    
                        <a href="/tags" class="menu gt-a-link">
                            标签
                        </a>
                    
                </div>
            
                <div class="nav-item">
                    
                        <a href="/post/about" class="menu gt-a-link">
                            关于
                        </a>
                    
                </div>
            
        </div>
    </div>
</nav>
    <div class="post-container">
        <div class="post-detail gt-bg-theme-color-second">
            <article class="gt-post-content">
                <h2 class="post-title">
                    为小白设计的电池教程（DSDT）
                </h2>
                <div class="post-info">
                    <time class="post-time gt-c-content-color-first">
                        · 2020-04-08 ·
                    </time>
                    
                        <a href="https://gzxiaobai.github.io/tag/2GXCvP3tq/" class="post-tags">
                            # 黑苹果
                        </a>
                    
                </div>
                <div class="post-content">
                    <pre><code>                                     为小白设计的电池教程（DSDT）
                                         编写者：G.Z.小白
</code></pre>
<p><strong>这个教程会尽量写的简单，只要你认真，你绝对看得懂！</strong><br>
此教程整理，修改，借鉴于：http://bbs.pcbeta.com/viewthread-1751487-1-1.html<br>
对其进行了完善，以及一些有问题的地方进行了修改。</p>
<h1 id="初步了解">初步了解</h1>
<p>实现原理 : 由于苹果无法使用ACPI EC中超过8位的寄存器（<strong>又叫EC缓冲区，Embedded Controller Buffer</strong>），我们需要利用Hotpatch的原理更名涉及到EC的Method使其失效并在新建的SSDT补丁中重新定义它们，使macOS能够通过SMC电池驱动正确识别电池EC信息。</p>
<p>好了，我觉得你应该得有个<strong>可以用的DSDT</strong>吧，如果没有请去提取自己的DSDT并反编译，排好错。具体见群文件的教程。<br>
首先打开我们的DSDT，搜索（Command + F）<strong>Embeddedcontrol</strong></p>
<figure data-type="image" tabindex="1"><img src="http://fp1.fghrsh.net/2020/04/08/b456b320c3ef57b623dab19f40c4013b.png" alt="b456b320c3ef57b623dab19f40c4013b.png" loading="lazy"></figure>
<p>OperationRegion名称，此为<strong>EC操作区</strong>的名称，一般名称为<strong>ERAM、ECF2、ECF3、ECOR</strong>等，并且有的机器可能不止一个</p>
<p>好了现在，我们找到了这里，仔细观察，发现它在EC0控制器下，具体路径是_SB.PCI0.LPCB.EC0。当然每个人的可能不一样，最后的EC0，还可能是ECDV、EC、H_EC。<br>
这里我们主要关注Field里的东西，就是那一堆四个字母的东西。在这一堆东西中，我们只要注意<strong>8位以上</strong>的就行（就是右边的数字）。因为电池驱动无法处理8位以上的字节，所以就需要我们手动来处理来。<br>
我们需要用到的工具：<strong>计算器（Mac自带）</strong>，<strong>Maciasl</strong>，<strong>新建一个txt文件</strong>。</p>
<p>打开txt文件，我们先把一下代码复制进去（我会把这个做成样例放在<strong>群文件</strong>）<br>
处理方法补丁如下</p>
<pre><code class="language-Swift">
# created by GZxioabai

# add method B1B2 
into method label B1B2 remove_entry;
into definitionblock code_regex . insert
begin
Method (B1B2, 2, NotSerialized)\n
{\n
Return(Or(Arg0, ShiftLeft(Arg1, 8)))\n
}\n
end;

 # add method B1B4
into method label B1B4 remove_entry;
into definitionblock code_regex . insert
begin
Method (B1B4, 4, NotSerialized)\n
{\n
   Store(Arg3, Local0)\n
   Or(Arg2, ShiftLeft(Local0, 8), Local0)\n
   Or(Arg1, ShiftLeft(Local0, 8), Local0)\n
   Or(Arg0, ShiftLeft(Local0, 8), Local0)\n
   Return(Local0)\n
}\n
end;

# add utility methods to read/write buffers from/to \_SB.PCI0.LPCB.EC0
into method label RE1B parent_label \_SB.PCI0.LPCB.EC0 remove_entry;
into method label RECB parent_label \_SB.PCI0.LPCB.EC0 remove_entry;
into Device label EC0 insert
begin
Method (RE1B, 1, NotSerialized)\n
{\n
   OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
   Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
   Return(BYTE)\n
}\n
Method (RECB, 2, Serialized)\n
// Arg0 - offset in bytes from zero-based \_SB.PCI0.LPCB.EC0\n
// Arg1 - size of buffer in bits\n
{\n
   ShiftRight(Arg1, 3, Arg1)\n
   Name(TEMP, Buffer(Arg1) { })\n
   Add(Arg0, Arg1, Arg1)\n
   Store(0, Local0)\n
   While (LLess(Arg0, Arg1))\n
   {\n
       Store(RE1B(Arg0), Index(TEMP, Local0))\n
       Increment(Arg0)\n
       Increment(Local0)\n
   }\n
   Return(TEMP)\n
}\n
end;

into method label WE1B parent_label \_SB.PCI0.LPCB.EC0 remove_entry;
into method label WECB parent_label \_SB.PCI0.LPCB.EC0 remove_entry;
into Device label EC0 insert
begin
Method (WE1B, 2, NotSerialized)\n
{\n
   OperationRegion(ERAM, EmbeddedControl, Arg0, 1)\n
   Field(ERAM, ByteAcc, NoLock, Preserve) { BYTE, 8 }\n
   Store(Arg1, BYTE)\n
}\n
Method (WECB, 3, Serialized)\n
// Arg0 - offset in bytes from zero-based EC\n
// Arg1 - size of buffer in bits\n
// Arg2 - value to write\n
{\n
   ShiftRight(Arg1, 3, Arg1)\n
   Name(TEMP, Buffer(Arg1) { })\n
   Store(Arg2, TEMP)\n
   Add(Arg0, Arg1, Arg1)\n
   Store(0, Local0)\n
   While (LLess(Arg0, Arg1))\n
   {\n
       WE1B(Arg0, DerefOf(Index(TEMP, Local0)))\n
       Increment(Arg0)\n
       Increment(Local0)\n
   }\n
}\n
end;

</code></pre>
<p>以上的这些东西是同用的处理方法，包括<em>B1B2（16字节处理），B1B4（32字节处理），WECB和RECB（这两个是处理32字节以上的）</em></p>
<h1 id="16位处理方法">16位处理方法</h1>
<p>接下来，我们来讲讲16位如何处理。</p>
<p>比如我们在Field下找到的这个<strong>16位的BADC</strong>，我们需要将它拆分掉，拆成来<strong>两个8字节</strong>，这样就能被电池驱动处理了。</p>
<p><strong>读取操作：</strong></p>
<p>我们还是先来解释一下吧，<strong>什么是读取什么是写入</strong>？在DSDT中常见的是下面两种语句。<br>
第一种语句（老）：</p>
<p><code>Store（BADC，ENC0）</code></p>
<p>在这里，Store语句中，<strong>BADC</strong>是<strong>读</strong>的操作，而<strong>ENC0</strong>是<strong>写</strong>的操作，解释一下，就是将<strong>BADC写入到ENC0</strong>，所以你可几个口诀就是“<strong>左读右写</strong></p>
<p>第二种语句（新）：</p>
<p><code>ENC0 = BADC</code></p>
<p>在这里，就刚好相反了，这里没有了Store，但意思还是<strong>将BADC写入到ENC0</strong>，所以<strong>BADC</strong>还是<strong>读</strong>，<strong>ENC0</strong>还是<strong>写</strong>。</p>
<p><strong>写入操作：</strong></p>
<p><code>Store（FB4，BADC）</code></p>
<p>在这里，Store语句中，<strong>FB4</strong>是<strong>读</strong>的操作，而<strong>BADC</strong>是<strong>写</strong>的操作，解释一下，就是<strong>将BADC写入到ENC0</strong>，所以你可几个口诀就是“<strong>左读右写</strong>”</p>
<p>那么其实很好理解了<strong>BADC = FB4</strong>这个就跟上面提到的反一下<br>
了解了这些那么你可以继续接下来的拆分工作了。</p>
<p>Field（声明字段）下处理补丁：<code>into Device label EC0 code_regex BADC,\s+16, replace_matched begin DCA0,8,DCA1,8, end;</code></p>
<p>我们先来理解一下这个，</p>
<ul>
<li><code>into</code>：<code>针对</code></li>
<li><code>Device label</code>：<code>关于这个设备范围里</code></li>
<li><code>EC0</code>:<code>设备的名称</code></li>
<li><code>code_regex</code>：<code>匹配搜索</code></li>
<li><code>BADC,\s+16</code>：<code>被搜索的代码，\s+16表示16字节</code></li>
<li><code>replace_matched</code>：<code>匹配替换</code></li>
<li><code>begin DCA0,8,DCA1,8, end</code>：<code>从什么什么开始，到什么什么结束，这里的意思就是，用于替换的是“DCA0,8,DCA1,8, ”</code></li>
</ul>
<p>那么整句话的意思就是，</p>
<p>在<code>设备EC0的范围内搜索16字节的BADC，如果有，就替换为“DCA0,8,DCA1,8,”</code></p>
<p>我们在来表示成一个处理结果：<code>BADC， 16，-----&gt;DCA0,8,DCA1,8,</code><br>
当然这只是在声明字段中进行拆分处理，我们还要在BADC<strong>被调用的地方</strong>进行处理。<br>
我们首先需要查找一下<strong>BADC</strong>在哪些地方被调用。（***重要提醒：没被调用的其实不需要拆分！意思是你根本不用去管它！***）</p>
<p>被调用的字段（一般在Method下）那里，对字段进行拆分：<br>
<strong>读</strong>的处理补丁：<code>into method label SMTF code_regex BADC replaceall_matched begin B1B2(DCA0,DCA1) end;</code></p>
<p>解释：</p>
<ul>
<li><code>into method label SMTF</code>：<code>针对Method为SMTF的这个范围内</code></li>
<li><code>code_regex</code>：<code>匹配（搜索）</code></li>
<li><code>BADC</code>：<code>被搜索的字段</code></li>
<li><code>replace_matched</code>：<code>替换匹配</code></li>
<li><code>begin B1B2(DCA0,DCA1) end</code>：<code>这是被替换的内容</code></li>
</ul>
<p>那么总的意思就是，</p>
<ul>
<li><code>在method为SMTF这个范围里面，搜索“BADC,\s+16”, ，如果有，就把它替换为“DCA0,8,DCA1,8,” 。</code></li>
</ul>
<p>那么最后的处理结果是：</p>
<p>未处理前：</p>
<pre><code class="language-Swift">            Method (SMTF, 1, NotSerialized)
            {
                If (LEqual (Arg0, Zero))
                {
                    Return (BADC)
                }

                If (LEqual (Arg0, One))
                {
                    Return (Zero)
                }

                Return (Zero)
            }
</code></pre>
<p>打了补丁之后：</p>
<pre><code class="language-Swift">            Method (SMTF, 1, NotSerialized)
            {
                If (LEqual (Arg0, Zero))
                {
                    Return (B1B2 (DCA0, DCA1))
                }

                If (LEqual (Arg0, One))
                {
                    Return (Zero)
                }

                Return (Zero)
            }
</code></pre>
<p>当然啦，这仅仅是BADC如果是<strong>读取</strong>的时候的处理，那要是碰到<strong>写入</strong>的时候，我们就要像下面这样处理，<strong>不能使用B1B2的方法了</strong><br>
比如：<br>
<strong>Store (Arg0, BADC)  （BADC是16位的情况）</strong><br>
需要改为：<br>
<strong>Store (ShiftRight(Arg0,8),DCA1) （DCA1是16位拆分后的第二个）</strong><br>
<strong>Store (Arg0,DCA0) （DCA0是16位拆分后的第一个）</strong><br>
那么补丁，我们就可以这样写：</p>
<p><code>into method label SMRW code_regex Store\s\(Arg3,\sBADC\) replaceall_matched begin Store(ShiftRight(Arg3,8),DCA1)\nStore(Arg3, DCA0) end;**</code></p>
<p>其中这段文字中的\s代表的是一个空格，\n代表的是换行，也就是回车，主要的是在搜索那里，需要注意符号转义，在任何符号前都要加一个反斜杠转义，也就是加一个\</p>
<p>那最后的处理结果是：<br>
未处理：</p>
<pre><code class="language-swift">Store (Arg0, BADC)
</code></pre>
<p>打了补丁后：</p>
<pre><code class="language-swift">Store (ShiftRight(Arg0,8),DCA1)
Store (Arg0,DCA0)
</code></pre>
<h1 id="32字节处理方法">32字节处理方法</h1>
<p>32位字段的处理方法其实跟16位一样，用到的是B1B4，区别就是，16位拆除<strong>2个</strong>，32拆除<strong>4个</strong><br>
在Field里查找32位的，这里我们也是举一个例子，比如<strong>B1CH</strong></p>
<p>补丁如下：<br>
<code>into Device label EC0 code_regex B1CH,\s+16, replace_matched begin CH10,8,CH11,8,CH12,CH13 end;</code><br>
处理结果为：<br>
<code>B1CH,32, ---—&gt; BC0H,8,BC1H,8,BC2H,8,BC3H,8,</code><br>
我们可以发现，这个跟16位的差不多，就是后面<strong>多拆2个</strong>，那就不用多废话解释了。<br>
我们直接讲在被调用的地方的处理（<strong>32字节基本不会有写入操作，也从未出现过</strong>）<br>
补丁如下：<br>
<code>into method label _BIF code_regex B1CH replaceall_matched begin B1B4(CH10,CH11,CH12,CH13) end;</code><br>
那这个也就不解释了，差不多的意思。其中<strong>B1B4</strong>是<strong>32位</strong>处理方法<br>
处理结果：<br>
未处理：</p>
<pre><code class="language-swift">            Method (_BIF, 0, NotSerialized)
            {
                Store (B1CH, IFCH)                                                  //未处理前
            }
</code></pre>
<p>打了补丁后：</p>
<pre><code class="language-swift">            Method (_BIF, 0, NotSerialized)
            {
                Store (B1B4 (BC0H, BC1H, BC2H, BC3H), IFCH)                  //把被调用B1CH两处拆分为4个字节
            }
</code></pre>
<h1 id="偏移量计算">偏移量计算</h1>
<p>到了32位以上的字段处理，我们会使用到<strong>RECB（读）<strong>和</strong>WECB（写）<strong>两个处理方法<br>
我先给你看两个例子：<br>
<strong>RECB(0x98, 64)</strong><br>
<strong>WECB (0x1C, 256, FB4)</strong><br>
我们来解释一下它们的组成部分，<strong>RECB(偏移量, 字段长度)</strong>，<strong>WECB(偏移量, 字段长度,未处理前的前参数 )</strong><br>
字段长度很好理解，64位就是64，128位就是128，256位就是256<br>
<strong>WECB</strong>中的</strong>未处理前的前参数</strong>，我们举个例子好理解一点<br>
比如：<br>
<strong>Store (FB4, SMD0)</strong><br>
<strong>SMD0</strong>是<strong>256位的需要处理的字段</strong>，在这里是<strong>写入</strong>，那么它的前参数，顾名思义就是前面那个<strong>FB4</strong><br>
那么其实，最主要的问题是<strong>偏移量</strong>了。<br>
举例1：</p>
<pre><code class="language-swift">Offset (0x04), （基地址）
CMCM,   8, //0x04
CMD1,   8, //0x05
CMD2,   8, //0x06
CMD3,   8, //0x07
Offset (0x18),
Offset (0x19), （基地址）
SMST,   8, //0x19
MBMN,   80, //0x1A
MBPN,   96, //0x24
GPB1,   8, //0x30
GPB2,   8, //0x31           
GPB3,   8, //0x32        
GPB4,   8, //0x33    
</code></pre>
<p>我们看这里的，<strong>MBMN</strong>是需要处理的<strong>80位字段</strong>，它的偏移量的计算就要涉及到它上面的<strong>基地址</strong>，我们看到了那个基地址是<strong>0x19</strong>，我们还可以发现它前面有个<strong>8位的SMST</strong>，我们将8除以8，得到1，再把0x19加上这个1，最后得到了<strong>0x1A</strong>，那么下面那个MBPN的偏移量怎么算呢，就是<strong>将前面的都加起来除以8</strong>，再加上<strong>基地址</strong>，就是8加上80得到88，除以8，等于11，转换为16进制就是B，0x19加上B，等于0x24.（<strong>注意的是，在除以8后的数字，一定要转换为16进制，再加上基地址！</strong>）<br>
举例二：</p>
<pre><code class="language-swift">Offset (0x53),      //（基地址）     
B0TP,   16,      // 从基地址起 ，为0x53   
B0VL,   16,      //16，为2个字节；  计算：上一个的起始地址0x53+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x55
B0CR,   16,      //16，为2个字节；  计算：上一个的起始地址0x55+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x57
B0AC,   16,      //16，为2个字节；  计算：上一个的起始地址0x57+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x59
B0ME,   16,      //16，为2个字节；  计算：上一个的起始地址0x59+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x5b
B0RS,   16,      //16，为2个字节；  计算：上一个的起始地址0x5b+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x5d
B0RC,   16,      //16，为2个字节；  计算：上一个的起始地址0x5d+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x5f
B0FC,   16,      //16，为2个字节；  计算：上一个的起始地址0x5f+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x61
B0MC,   16,     //16，为2个字节；  计算：上一个的起始地址0x61+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x63
B0MV,   16,     //16，为2个字节；  计算：上一个的起始地址0x63+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x65
B0ST,   16,      //16，为2个字节；  计算：上一个的起始地址0x65+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x67
B0CC,   16,      //16，为2个字节；  计算：上一个的起始地址0x67+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x69
B0DC,   16,      //16，为2个字节；  计算：上一个的起始地址0x69+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x6b
B0DV,   16,      //16，为2个字节；  计算：上一个的起始地址0x6b+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x6d
B0SI,   16,      //16，为2个字节；  计算：上一个的起始地址0x6d+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x6f
B0SN,   32,     //32，为4个字节；  计算：上一个的起始地址0x6f+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x71      
B0MN,   96,    //96，为12个字节  计算：上一个的起始地址0x71+0x4（上一个的32位占了4个字节，10转为16进制为0x4）值为0x75
B0DN,   64,     // 64，为8个字节；计算：上一个的起始地址0x75+0xc（上一个的96位占了12个字节，10转为16进制为0xc）值为0x81
B0CM,   48,    //  计算：上一个的起始地址0x81+0x8（64位占了8个字节，10转为16进制为0x8）值为0x89
</code></pre>
<p>这里我就不说明了，自己看右边的注释理解一下吧。<br>
举例3：</p>
<pre><code class="language-swift">Offset (0x5D),     //（基地址）  
ENIB,   16,     // 16，为2个字节；   从基地址起 ，为0x5D
ENDD,   8,     //8，为1个字节；  计算：上一个的起始地址0x5D+0x2（上一个的16位占了2个字节，10转为16进制为0x2）值为0x5F
SMPR,   8,     //8，为1个字节；  计算：上一个的起始地址0x5F+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x60
SMST,   8,     //8，为1个字节；  计算：上一个的起始地址0x60+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x61
SMAD,   8,   //8，为1个字节；  计算：上一个的起始地址0x61+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x62
SMCM,   8,     //8，为1个字节；  计算：上一个的起始地址0x62+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x63
SMD0,   256,    //256，为32个字节；  计算：上一个的起始地址0x63+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x64
BCNT,   8,      //8，为1个字节；  计算：上一个的起始地址0x64+0x20（上一个的256位占了32个字节，10转为16进制为0x20）值为0x84
SMAA,   24,      //8，为1个字节；  计算：上一个的起始地址0x84+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x85
</code></pre>
<p>举例4  最为简单：</p>
<pre><code class="language-swift">            Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                    Offset (0x04),
                    FLD0,   64          // 64，为8个字节；   从基地址起 ，为0x04（偏移量）
                }

            Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                    Offset (0x04),
                    FLD1,   128          // 128，为16个字节；   从基地址起 ，为0x04（偏移量）
                }

            Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                    Offset (0x04),
                    FLD2,   192          // 192，为24个字节；   从基地址起 ，为0x04（偏移量）
                }

            Field (ERAM, ByteAcc, NoLock, Preserve)
                {
                    Offset (0x04),
                    FLD3,   256          // 256，为32个字节；   从基地址起 ，为0x04（偏移量）
                }
</code></pre>
<p>举例五 特殊：</p>
<pre><code class="language-swift">OperationRegion (SMBX, EmbeddedControl, 0x18, 0x28)            //第三个值是起始地址
Field (SMBX, ByteAcc, NoLock, Preserve)
{
        PRTC,   8,      //8，为1个字节；  上面第三个值是起始地址0x18
        SSTS,   5,      //计算：上一个的起始地址0x18+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x19
            ,   1,
        ALFG,   1,
        CDFG,   1,      //上面 5+1+1+1才凑够8位（1字节）
        ADDR,   8,    //8，为1个字节；计算：上一个的起始地址0x19+0x1（上面 5+1+1+1才凑够8位占了1个字节，10转为16进制为0x1）值为0x19     0x1A
        CMDB,   8, //8，为1个字节；  计算：上一个的起始地址0x1A+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x1B   
        BDAT,   256, //256，为32个字节；计算：上一个的起始地址0x1B+0x1（上一个的8位占了1个字节，10转为16进制为0x1）值为0x1C
        BCNT,   8,
            ,   1,
        ALAD,   7,
        ALD0,   8,
        ALD1,   8

}
</code></pre>
<h1 id="32位以上字段的处理包括64128256等">32位以上字段的处理（包括64，128，256等）</h1>
<p>在Field下，我们需要对其进行<strong>重命名</strong>使其失效。<br>
补丁如下：</p>
<p><code>into Device label EC0 code_regex (SMD0,)\s+(256) replace_matched begin SMDX,%2,//%1%2 end;</code></p>
<p>这里需要注意的是<strong>要打括号</strong>！，还有后面的<strong>SMDX</strong>是重命名后的结果，<strong>%2,//%1%2</strong>这个也是要加上的！<br>
接下来在被调用的地方进行处理：</p>
<p><em><strong>读取调用</strong></em></p>
<p><strong>Store (SMD0, FB4)</strong><br>
我们要用到RECB，补丁如下：</p>
<p><code>into method label MHPF code_regex SMD0 replaceall_matched begin RECB(0x1C, 256) end;</code><br>
处理结果为：<code>Store (SMD0, FB4) —&gt; Store (RECB (0x1C, 0x0100), FB4)</code></p>
<p><em><strong>写入调用</strong></em></p>
<p><strong>Store (FB4, SMD0)</strong><br>
我们要用到WECB，补丁如下：</p>
<p><code>into method label MHPF code_regex Store\s\(FB4,\sSMD0\) replaceall_matched begin WECB(0x1C,256,FB4) end；</code></p>
<p>值得注意的是，我们这边是<strong>将整个Store语句进行了替换</strong>，这也是<strong>WECB</strong>处理的不同之处。<br>
处理结果：<code>Store (FB4, SMD0) —&gt; WECB (0x1C, 256, FB4)</code></p>
<h1 id="mutex确认最后检查">Mutex确认，最后检查</h1>
<p>确保DSDT里的<strong>Mutex</strong>都是<strong>0x00</strong>，不然可能会出现电量显示0%的情况。<br>
在DSDT里搜索<strong>Mutex</strong>，如果有的不是0x00，你就自己手动改成0x00。</p>
<h1 id="补充">补充</h1>
<p>当电池有时能正常显示电量，有时不能会出现一个小叉，则可能是多个电池的位置导致的，如图有两个位置，分别为“BAT0”和“BAT1”，我们需要禁用掉“BAT1”这个位置，以达到正常读取电量</p>

                </div>
            </article>
        </div>

        

        
		
		
			<script src='https://unpkg.com/valine/dist/Valine.min.js'></script>

<style>
	div#vcomments{
		width:100%;
		max-width: 1000px;
		padding: 2.5%
	}
</style>


	<div id="vcomments"></div>

<script>
	new Valine({
		el: '#vcomments',
		appId: 'hcgePHaJOceH3R36dS7FxVSJ-gzGzoHsz',
		appKey: '7RPXugMe92rdtnjtiCD1P2Lm',
		avatar: '',
		pageSize: 5,
		recordIp: true,
		placeholder: 'Just Go Go'
	});
</script>
		

        <div class="site-footer gt-c-content-color-first">
    <div class="slogan gt-c-content-color-first">这是一个正常的人（确信）</div>
    <div class="social-container">
        
            
                <a href="https://github.com/GZXiaoBai" target="_blank">
                    <i class="fab fa-github gt-c-content-color-first"></i>
                </a>
            
        
            
        
            
        
            
        
            
        
            
        
    </div>
    <div class="footer-info">
        Powered by <a href="https://github.com/getgridea/gridea" target="_blank">Gridea</a>
    </div>
    <div>
        Theme by <a href="https://imhanjie.com/" target="_blank">imhanjie</a>, Powered by <a
                href="https://github.com/getgridea/gridea" target="_blank">Gridea | <a href="https://gzxiaobai.github.io/atom.xml" target="_blank">RSS</a></a>
    </div>
</div>

<script>
    hljs.initHighlightingOnLoad()
</script>

    </div>
</div>
</body>
</html>
